#ifndef NETWORK_DV_SOURCE_H
#define NETWORK_DV_SOURCE_H
#include "dvsource.h"
#include "dvlog.h"
#include <map>
#include <vector>
using namespace std;
#include <StringUtil.h>


class IPAddressFilter
{
public:
	IPAddressFilter()
	{
		len = 0;
	}
	IPAddressFilter(const IPAddress& addr, int len = -1)
	{
		this->addr = addr;
		if(len < 0)
			this->len = addr.GetLength();
		else
			this->len = len;
	}
	IPAddressFilter(const IPAddressFilter& flt)
	{
		this->operator=(flt);
	}
	IPAddressFilter& operator=(const IPAddressFilter& flt)
	{
		if(this == &flt)
			return *this;
		addr = flt.addr;
		len = flt.len;
		return *this;
	}
	bool IsMatch(const IPAddress& a)
	{
		return a.Match(addr, len);
	}
	bool Parse(const string& str)
	{
		vector<string> parts;
		split_string(str, string("/"), parts);
		if(parts.size() == 0 || parts.size() > 2)
		{
			return false;
		}
		if(!ParseString(parts[0], addr) || !addr.IsValid())
		{
			return false;
		}
		len = addr.GetLength();
		if(parts.size() == 2 && !ParseString(parts[1], len))
		{
			return false;
		}
        if(len < 0 || len > addr.GetLength())
		{
			return false;
		}
		return true;
	}
	string ToString() const
	{
		ostringstream ostr;
		ostr << addr;
		if(len < addr.GetLength())
		{
			ostr << '/' << len;
		}
		return ostr.str();
	}
	IPAddress	addr;
	socklen_t	len;
};

inline istream& operator>>(istream& istr, IPAddressFilter& flt)
{
	string str;
	istr >> str;
	if(!flt.Parse(str))
		istr.setstate(ios::failbit);
	return istr;
}
inline ostream& operator<<(ostream& ostr, const IPAddressFilter& flt)
{
	ostr << flt.ToString();
	return ostr;
}


class NetworkDVSource : public IDVSource
{
public:
	NetworkDVSource(sa_family_t sa_family, in_port_t rcv_port, const vector<IPAddressFilter>& src_filter, int32_t log_period = 0);
	virtual bool Init();
	virtual DVPacket GetPacket();
	virtual bool Cleanup();
	bool JoinGroup(const IPAddress& group);
	bool JoinSourceGroup(const IPAddress& source, const IPAddress& group);
	bool SetInitLogThreshold(double ilt);
	double GetInitLogThreshold() const;
	bool SetFluctuateThreshold(double ft);
	double GetFluctuateThreshold() const;
	void OnPacketReceive(const DVPacket& pkt);
	void WriteLog();
private:
	sa_family_t sa_family;
	in_port_t	rcv_port;
	vector<IPAddressFilter>	src_filters;
	IPAddress	source;
	IPAddress	group;
	Socket		sock;
	char		buffer[65536];
	int64_t		log_period;
	map<IPEndPoint, SourceStat> candi_sources;
	map<IPEndPoint, NetworkSourceLog> tracked_sources;
	int64_t		log_start_time;
	double		init_log_threshold;
	double		fluctuate_threshold;
};


#endif // !defined NETWORK_DV_SOURCE_H

